home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / et / et-2_2.lha / et2.2 / src / Font.C < prev    next >
C/C++ Source or Header  |  1990-12-06  |  10KB  |  484 lines

  1. #include <stdio.h>
  2.  
  3. #include "Font.h"
  4. #include "Error.h"
  5. #include "String.h"
  6. #include "WindowSystem.h"
  7.  
  8. #define FACES       5    /* Bold, Italic, Underline, Outline, Shadow */
  9. #define MAXFACES    32   /* 2**FACES */
  10. #define MAXFAMILIES 30
  11. #define FONTTABLE  "FontTab"
  12. #define FontNameTemplate "%s%02d%s"
  13.  
  14. Font *gSysFont,
  15.      *gApplFont,
  16.      *gFixedFont;
  17.        
  18. class FontManager *gFontManager;
  19. char *FontLib;
  20.  
  21. SimpleMetaImpl(Font)
  22. {
  23.     sprintf(buf, "%s", ((Font*) addr)->AsString());
  24. }
  25.  
  26. //---- Font --------------------------------------------------------------
  27.  
  28. Font *new_Font(GrFont font, int size, GrFace face)
  29.     return gFontManager->MapFont(font, size, face);
  30. }
  31.  
  32. Font *Font::WithFace(GrFace fc)
  33. {
  34.     return new_Font(family, size, fc);
  35. }
  36.  
  37. Font *Font::WithSize(int sz)
  38. {
  39.     return new_Font(family, sz, face);
  40. }
  41.  
  42. bool Font::Loaded()
  43. {
  44.     return TRUE;
  45. }
  46.  
  47. Font *Font::Load()
  48. {
  49.     if (! Loaded() && LoadFont())
  50.     return 0;
  51.     return this;
  52. }
  53.     
  54. char *Font::AsString()
  55. {
  56.     return form("%s.%d.%s", gFontManager->IdToName(Fid()), Size(),
  57.                         gFontManager->StyleString(Face()));
  58. }
  59.  
  60. int Font::Width(register byte *s, register int l)
  61. {
  62.     register int w= 0;
  63.     
  64.     if (s) {
  65.     if (l < 0) {
  66.         while(*s)
  67.         w+= cw[*s++];
  68.     } else {
  69.         while(--l >= 0)
  70.         w+= cw[*s++];
  71.     }
  72.     }
  73.     return w;
  74. }
  75.  
  76. int Font::MaxWidth(int l)
  77. {
  78.     if (width < 0) {
  79.     register int i;
  80.     
  81.     width= 0;
  82.     for (i= 0; i< 255; i++)
  83.         width= max(width, cw[i]);
  84.     }
  85.     return l*width;
  86. }
  87.  
  88. Rectangle Font::BBox(register byte *s, register int l)
  89. {
  90.     register int w= 0;
  91.     
  92.     if (s == 0)
  93.     return gRect0;
  94.     if (l < 0) {
  95.     while(*s)
  96.         w+= cw[*s++];
  97.     } else {
  98.     while(--l >= 0)
  99.         w+= cw[*s++];
  100.     }
  101.     return Rectangle(0, ht, w, ht+bs);
  102. }
  103.  
  104. Metric Font::GetMetric(register byte *s, register int l)
  105. {
  106.     register int w= 0;
  107.     
  108.     if (s == 0)
  109.     return Metric(0);
  110.     if (l < 0) {
  111.     while(*s)
  112.         w+= cw[*s++];
  113.     } else {
  114.     while(--l >= 0)
  115.         w+= cw[*s++];
  116.     }
  117.     return Metric(w, Ascender()+Descender(), Ascender());
  118. }
  119.  
  120. Metric Font::GetMetric(byte c)
  121. {
  122.     return Metric(Width(c), Ascender()+Descender(), Ascender());
  123. }
  124.  
  125. Rectangle Font::BBox(register byte c, Point pos)
  126. {
  127.     return Rectangle(pos.x, pos.y-Ascender(), Width(c), Spacing());
  128. }
  129.  
  130. bool Font::LoadFont()
  131. {
  132.     return FALSE;
  133. }
  134.  
  135. Font *Font::MakeFont(Font**, GrFace)
  136. {
  137.     return this;
  138. }
  139.  
  140. Point Font::AdjustString(register byte *s, Point p, GrVAdjust va, GrHAdjust ha)
  141. {
  142.     register int w= 0;
  143.     
  144.     if (s)
  145.     while(*s)
  146.        w+= cw[*s++];
  147.     
  148.     switch (ha) {
  149.     case eAdjHRight:
  150.     p.x-= w;
  151.     break;
  152.     case eAdjHCenter:
  153.     p.x-= w/2;
  154.     break;
  155.     default:
  156.     break;
  157.     }
  158.     switch (va) {
  159.     case eAdjVBottom:
  160.     p.y-= bs;
  161.     break;
  162.     case eAdjVCenter:
  163.     p.y+= (ht-bs)/2;
  164.     break;
  165.     case eAdjVTop:
  166.     p.y+= ht;
  167.     break;
  168.     case eAdjVBase:
  169.     break;
  170.     }
  171.     return p;
  172. }
  173.  
  174. DevBitmap *Font::CharAsBitmap(byte, Point*)
  175. {
  176.     return 0;
  177. }
  178.  
  179. void Font::CheckChar(byte c)
  180. {
  181.     register FontPtr *fdptr;
  182.     int facebit, ff;
  183.     
  184.     fdptr= gFontManager->MapFamilySize((GrFont)family, size);
  185.     ff= eFacePlain;
  186.     facebit= eFaceBold;
  187.     while (face != ff) {
  188.     if (face & facebit) {
  189.         fdptr[ff|facebit]->MakeChar(fdptr[ff], (GrFace)facebit, c, fdptr[ff & 7]);
  190.         ff|= facebit;
  191.     }
  192.     facebit<<= 1;
  193.     }
  194. }
  195.  
  196. void Font::MakeChar(Font*, GrFace, byte, Font*)
  197. {
  198. }
  199.  
  200. ostream& Font::StoreOn(ostream &s)
  201. {
  202.     return s << (int)family SP << (int)size SP << (int)face SP;
  203. }
  204.  
  205. ostream& operator<< (ostream &s, FontPtr &fp)
  206. {
  207.     return fp->StoreOn(s);
  208. }
  209.  
  210. istream& operator>> (istream &s, FontPtr &fp)
  211. {
  212.     GrFont fid;
  213.     GrFace fc;
  214.     int ps;
  215.     
  216.     s >> Enum(fid) >> ps >> Enum(fc);
  217.     fp= gFontManager->MapFont(fid, ps, fc);
  218.     return s;
  219. }
  220.  
  221. //---- misc ---------------------------------------------------------------------
  222.  
  223. char *FontManager::StyleString(GrFace face)
  224. {
  225.     static char buf[20];
  226.     char *cp= buf;
  227.     if (face == eFacePlain)
  228.     *cp++= 'r';
  229.     else {
  230.     if (face & eFaceBold)
  231.         *cp++= 'b';
  232.     if (face & eFaceItalic)
  233.         *cp++= 'i';
  234.     if (face & eFaceUnderline)
  235.         *cp++= 'u';
  236.     if (face & eFaceOutline)
  237.         *cp++= 'o';
  238.     if (face & eFaceShadow)
  239.         *cp++= 's';
  240.     }
  241.     *cp= '\0';
  242.     return buf;
  243. }
  244.  
  245. //---- FontManager -------------------------------------------------------------
  246.  
  247. FontManager::FontManager(char *etdir)
  248. {
  249.     FontLib= fontDir= etdir;
  250.     fmap= new FontFamilyPtr[MAXFAMILIES];
  251. }
  252.  
  253. FontManager::~FontManager()
  254. {
  255.     for (int f= 0; f < MAXFAMILIES; f++)
  256.     SafeDelete(fmap[f]);
  257.     SafeDelete(fmap);
  258. }
  259.  
  260. bool FontManager::Init()
  261. {
  262.     char *psname, family[40], fontname[80], name[40], buf[80];
  263.     FILE *fonts;
  264.     int fid, psfont, c, size;
  265.     bool firstchar;
  266.     GrFace style;
  267.     
  268.     if ((fonts= fopen(form("./%s", FONTTABLE), "r")) == 0)
  269.     if ((fonts= fopen(form("%s/%s", fontDir, FONTTABLE), "r")) == 0)
  270.         Fatal("FontManager::FontManager", "can't locate %s", FONTTABLE);
  271.        
  272.     // read available fonts
  273.     while (fscanf(fonts, "%d %s %s %d", &fid, name, family, &psfont) == 4) {
  274.     if (fid < 0 || fid >= MAXFAMILIES) {
  275.         Error("FontManager::FontManager", "fid out of range", FALSE);
  276.         continue;
  277.     }
  278.     fmap[fid]= new FontFamily((GrFont)fid, name, family, psfont);
  279.     firstchar= TRUE;
  280.     style= eFacePlain;
  281.     
  282.     while (c= fgetc(fonts)) {
  283.         switch (c) {
  284.         case EOF:
  285.         break;
  286.         case 'r':
  287.         if (firstchar)
  288.             firstchar= FALSE;
  289.         style= eFacePlain;
  290.         break;
  291.         case 'b':
  292.         if (firstchar) {
  293.             style= eFacePlain;
  294.             firstchar= FALSE;
  295.         }
  296.         style= (GrFace)(style|eFaceBold);
  297.         break;
  298.         case 'i':
  299.         if (firstchar) {
  300.             style= eFacePlain;
  301.             firstchar= FALSE;
  302.         }
  303.         style= (GrFace)(style|eFaceItalic);
  304.         break;
  305.         case '\n':
  306.         goto out;
  307.         default:
  308.         if (Isdigit(c)) {
  309.             size= 0;
  310.             while (Isdigit(c)) {
  311.             size= size * 10 + (c-'0');
  312.             c= fgetc(fonts);
  313.             }
  314.             ungetc(c, fonts);
  315.             sprintf(fontname, FontNameTemplate, family, size,
  316.                     gFontManager->StyleString(style));
  317.             fmap[fid]->AddFont(fontname, style, size);
  318.             firstchar= TRUE;
  319.         }
  320.         break;
  321.         }
  322.     }
  323. out:    ;
  324.     }
  325.  
  326.     fclose(fonts);
  327.     
  328.     if ((psname= gSystem->getenv("ET_FONT_SIZE")) == 0)
  329.     psname= "12";
  330.     size= atoi(psname);
  331.     
  332.     gSysFont= new_Font(eFontChicago, size);
  333.     gApplFont= new_Font(eFontMonaco, size);
  334.     gFixedFont= new_Font(eFontCourier, size);
  335.  
  336.     return FALSE;
  337. }
  338.  
  339. Font *FontManager::MakeFont(char*, GrFont, int, GrFace)
  340. {
  341.     return 0;
  342. }
  343.     
  344. Font *FontManager::MapFont(GrFont font, int size, GrFace face)
  345. {
  346.     if (font < 0 || font >= MAXFAMILIES || fmap[font] == 0)
  347.     return gSysFont;
  348.     return MapFamily(font)->MapSizeFace(size, face);
  349. }
  350.  
  351. int FontManager::NameToId(char *fontname)
  352. {
  353.     for (int i= 0; i < MAXFAMILIES; i++)
  354.     if (fmap[i] && fmap[i]->Name() && strcmp(fmap[i]->Name(), fontname) == 0)
  355.         return i;
  356.     return -1;
  357. }
  358.  
  359. char *FontManager::IdToName(GrFont fid)
  360. {
  361.     if (fid >= 0 && fid < MAXFAMILIES && fmap[fid])
  362.     return fmap[fid]->Name();
  363.     return 0;
  364. }
  365.  
  366. Font *FontManager::ScaleFont(Font*, GrFont, int, GrFace)
  367. {
  368.     return 0;
  369. }
  370.  
  371. //---- FontFamily --------------------------------------------------------------
  372.  
  373. FontFamily::FontFamily(GrFont fid, char *nm, char *family, bool psfont)
  374. {
  375.     familyid= fid;
  376.     name1= strsave(family);
  377.     name= strsave(nm);
  378.     ispsfont= psfont;
  379. }
  380.  
  381. FontFamily::~FontFamily()
  382. {
  383.     int s, ss, fc;
  384.     
  385.     for (s= 0; s < SIZES; s++) {
  386.     if (smap[s]) {
  387.         for (ss= s+1; ss < SIZES; ss++)
  388.         if (smap[s] == smap[ss])
  389.             smap[ss]= 0;    // don't delete smap twice
  390.         for (fc= 0; fc < MAXFACES; fc++)
  391.         if (smap[s][fc] && smap[s][fc]->Size())
  392.             SafeDelete(smap[s][fc]);
  393.         SafeDelete(smap[s]);
  394.     }
  395.     }
  396.     SafeDelete(name1);
  397.     SafeDelete(name);
  398. }
  399.  
  400. void FontFamily::AddFont(char *fontname, GrFace fc, int ps)
  401. {
  402.     int internalsize;
  403.     FontPtr *fdptr;
  404.     
  405.     if (ps < MINSIZE || ps > MAXSIZE)
  406.     Error("FontFamily::AddFont:", "size out of range", FALSE);
  407.     if (fc < 0 || fc >= MAXFACES)
  408.     Error("FontFamily::AddFont:", "face out of range", FALSE);
  409.     
  410.     internalsize= ps-MINSIZE;
  411.     if (smap[internalsize] == 0)
  412.     smap[internalsize]= new FontPtr[MAXFACES];
  413.     fdptr= smap[internalsize];
  414.     
  415.     fdptr[fc]= gFontManager->MakeFont(fontname, familyid, ps, fc);
  416. }
  417.  
  418. Font **FontFamily::MapSize(int size)
  419. {
  420.     Font *fp= 0, **ffp= 0;
  421.     register int s, try, i;
  422.     
  423.     size= range(MINSIZE, MAXSIZE, size);
  424.     s= size-MINSIZE;
  425.     
  426.     if (smap[s])
  427.     return smap[s];
  428.     
  429.     // try twice a bigger font
  430.     try= size * 2;
  431.     if (try <= MAXSIZE && smap[try-MINSIZE]
  432.                     && (fp= smap[try-MINSIZE][eFacePlain]))
  433.     fp= gFontManager->ScaleFont(fp->Load(), familyid, size, eFacePlain);
  434.     
  435.     if (fp == 0) {  // try twice a smaller font
  436.     try= size / 2;
  437.     if (try >= MINSIZE && smap[try-MINSIZE]
  438.                     && (fp= smap[try-MINSIZE][eFacePlain]))
  439.         fp= gFontManager->ScaleFont(fp->Load(), familyid, size, eFacePlain);
  440.     }
  441.     
  442.     if (fp == 0) {  // try nearest font
  443.     for (i= 1; i < MAXSIZE-MINSIZE; i++) {
  444.         if (s-i >= 0 && (smap[s]= smap[s-i]))
  445.         break;
  446.         if (s+i <= MAXSIZE-MINSIZE && (smap[s]= smap[s+i]))
  447.         break;
  448.     }
  449.     }
  450.     
  451.     if (fp) {
  452.     if (smap[s] == 0)
  453.         smap[s]= new FontPtr[MAXFACES];
  454.     smap[s][eFacePlain]= fp;
  455.     }
  456.     
  457.     return smap[s];
  458. }
  459.  
  460. Font *FontFamily::MapSizeFace(int size, GrFace face)
  461. {
  462.     int ff, facebit;
  463.     Font **fdptr= MapSize(size);
  464.     
  465.     if (face < 0 || face >= MAXFACES)
  466.     face= eFacePlain;
  467.     
  468.     if (fdptr[face])
  469.     return fdptr[face]->Load();
  470.     
  471.     ff= eFacePlain;
  472.     facebit= eFaceBold;
  473.     while (face != ff) {
  474.     if (face & facebit) {
  475.         if (fdptr[ff | facebit] == 0)
  476.         fdptr[ff | facebit]= fdptr[ff]->Load()->MakeFont(fdptr, (GrFace)facebit);
  477.         ff|= facebit;
  478.     }
  479.     facebit<<= 1;
  480.     }
  481.     return fdptr[face];
  482. }
  483.